﻿using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SM
{
    public class SMUtil
    {
        private SMUtil()
        {
        }

        #region SM2
        /// <summary>
        /// 生成秘钥对
        /// </summary>
        /// <returns></returns>
        public static SM2KeyPair GenerateKeyPair()
        {
            return SM2Util.GenerateKeyPair();
        }

        /// <summary>
        /// 使用公钥加密
        /// </summary>
        /// <param name="pubk"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string Sm2Encrypt(string pubk, string data)
        {
            byte[] sourceData = Encoding.UTF8.GetBytes(data);
            return SM2Util.Encrypt(Util.hexToByte(pubk), sourceData);
        }

        /// <summary>
        /// 使用私钥解密
        /// </summary>
        /// <param name="prik"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string Sm2Decrypt(string prik, string data)
        {
            return Encoding.UTF8.GetString(SM2Util.Decrypt(Util.hexToByte(prik), Util.hexToByte(data)));
        }

        /// <summary>
        /// 使用私钥签名
        /// </summary>
        /// <param name="data"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string Sign(string data, string privateKey)
        {
            // 获取签名串
            byte[] signText = Encoding.UTF8.GetBytes(data);
            byte[] prvkey = Hex.Decode(privateKey);
            return ByteUtil.ToHexString(SM2Util.Sign(signText, prvkey));
        }

        /// <summary>
        /// 使用公钥验证
        /// </summary>
        /// <param name="data"></param>
        /// <param name="sign"></param>
        /// <param name="pubk"></param>
        /// <returns></returns>
        public static bool Verify(string data, string sign, string pubk)
        {
            // 获取签名串
            byte[] signText = Encoding.UTF8.GetBytes(data);
            byte[] signbs = Hex.Decode(sign);
            return SM2Util.verify(pubk, signText, signbs); 
        }


        #endregion

        #region SM3
        /// <summary>
        /// 数据摘要
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string Sm3Encrypt(string data)
        {
            byte[] md = new byte[32];
            byte[] msg1 = Encoding.UTF8.GetBytes(data);
            SM3Digest sm3 = new SM3Digest();
            sm3.BlockUpdate(msg1, 0, msg1.Length);
            sm3.DoFinal(md, 0);
            return ByteUtil.ToHexString(md);
        }

        #endregion

        #region SM4
        /// <summary>
        /// SM4加密
        /// </summary>
        /// <param name="plaintext"></param>
        /// <param name="sm4Key"></param>
        /// <returns></returns>
        public static string Sm4Encrypt(string plaintext, string sm4Key)
        {
            byte[] sourceData = Encoding.UTF8.GetBytes(plaintext);
            byte[] keyBytes = Encoding.UTF8.GetBytes(sm4Key);
            return Sm4Encrypt(sourceData, keyBytes);  
        }

        /// <summary>
        /// SM4加密 采用SM4/ECB/PKCS5Padding
        /// </summary>
        /// <param name="sourceData">源数据</param>
        /// <param name="keyBytes">sm4秘钥</param>
        /// <returns>Base64字符串</returns>
        public static string Sm4Encrypt(byte[] sourceData, byte[] keyBytes)
        {
            KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
            IBufferedCipher inCipher = CipherUtilities.GetCipher("SM4/ECB/PKCS5Padding");
            inCipher.Init(true, key);
            byte[] cipher = inCipher.DoFinal(sourceData);
            string str = Convert.ToBase64String(cipher);
            return str;
        }

        /// <summary>
        /// SM4解密 采用SM4/ECB/PKCS5Padding
        /// </summary>
        /// <param name="base64Str">Base64字符串</param>
        /// <param name="sm4Key">sm4秘钥</param>
        /// <returns></returns>
        public static string Sm4Decrypt(string base64Str, string sm4Key)
        {
            byte[] sourceData = Convert.FromBase64String(base64Str);
            byte[] keyBytes = Encoding.UTF8.GetBytes(sm4Key);
            return Sm4Decrypt(sourceData, keyBytes);
        }

        /// <summary>
        /// SM4解密 采用SM4/ECB/PKCS5Padding
        /// </summary>
        /// <param name="sourceData">源数据</param>
        /// <param name="keyBytes">sm4秘钥</param>
        /// <returns></returns>
        public static string Sm4Decrypt(byte[] sourceData, byte[] keyBytes)
        {
            KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
            IBufferedCipher outCipher = CipherUtilities.GetCipher("SM4/ECB/PKCS5Padding");
            outCipher.Init(false, key);
            byte[] cipher = outCipher.DoFinal(sourceData);
            string ans = Encoding.UTF8.GetString(cipher);
            return ans;
        }

        #endregion 

    }

}
